package org.geekbang.thinking.in.spring.ioc.overview.dependency.injecttion;

import org.geekbang.thinking.in.spring.ioc.overview.annotation.Super;
import org.geekbang.thinking.in.spring.ioc.overview.domain.User;
import org.geekbang.thinking.in.spring.ioc.overview.repository.UserRepository;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.env.Environment;

import java.util.Map;

/**
 * 依赖注入示例
 */
public class DependencyInjectionDemo {

    public static void main(String[] args) {
        // 配置 XML 文件
        // 启动 Spring 应用上下文
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("META-INF/dependency-injection-context.xml");

        // 按类型注入（集合）
        // injectionByType(beanFactory);

        // 依赖来源一：自定义 Bean
        UserRepository userRepository = (UserRepository) applicationContext.getBean("userRepository");

        // 依赖来源二：依赖注入（内建依赖）
        System.out.println(userRepository.getBeanFactory());
        System.out.println(applicationContext == userRepository.getBeanFactory());  // false
        // 依赖查找（报错）
        // 原因：组合模式：ApplicationContext 中维护了一个 BeanFactory
        // System.out.println(applicationContext.getBean(BeanFactory.class));
        ConfigurableApplicationContext cac = (ConfigurableApplicationContext) applicationContext;
        System.out.println(userRepository.getBeanFactory() == cac.getBeanFactory());    // true

        // ObjectFactory<ApplicationContext> userObjectFactory = userRepository.getObjectFactory();
        // System.out.println(userObjectFactory.getObject());

        // System.out.println(beanFactory == userRepository.getObjectFactory().getObject());

        // 依赖来源三：容器内建 Bean
        // Environment environment = applicationContext.getBean(Environment.class);
        // System.out.println("获取 Environment 类型的 Bean：" + environment);
    }

    private static void whoIsIocContainer(UserRepository userRepository, ApplicationContext applicationContext) {
        // ConfigurableApplicationContext <- ApplicationContext <- BeanFactory

        // 这个表达式为什么不成立
        System.out.println(userRepository.getBeanFactory() == applicationContext);
        // ApplicationContext is BeanFactory
    }

    private static void injectionByType(BeanFactory beanFactory) {
        UserRepository userRepository = (UserRepository) beanFactory.getBean("userRepository");
        System.out.println(userRepository.getUsers());
    }
}
